#ifndef _LIGHT_H_
#define _LIGHT_H_

#include <glm/glm.hpp>
#include <variant>
#include <SECore/Reflect.h>

namespace SEngine
{
    class LightCommon
    {
    public:
        void SetColor(glm::vec3 color) { m_color = color; }
        glm::vec3 GetColor() { return m_color; }
        void SetEnergy(float energy) { m_energy = energy; }
        float GetEnergy() { return m_energy; }
    protected:
        glm::mat4 & PacketImpl(glm::mat4 & data) {
            data[1] = glm::vec4{m_color, m_energy};
            return data;
        }
    protected:
        glm::vec3   m_color{1.0f};
        float       m_energy{1.0f};
    };
    
    class LightPosition
    {
    public:
        void SetPos(glm::vec3 pos) { m_pos = pos; }
        glm::vec3 GetPos() { return m_pos; }
    protected:
        glm::mat4 & PacketImpl(glm::mat4 & data) {
            data[0] = glm::vec4{m_pos, data[0].w};
            return data;
        }
    protected:
        glm::vec3 m_pos{0.0f};
    };
    
    class LightDirect
    {
    public:
        void SetDirect(glm::vec3 dir) { m_dir = dir; }
        glm::vec3 GetDirect() { return m_dir; }
    protected:
        glm::mat4 & PacketImpl(glm::mat4 & data) {
            data[2] = glm::vec4{m_dir, 0.0f};
            return data;
        }
    protected:
        glm::vec3 m_dir{1.0f, 0.0f, 0.0f};
    };
    
    class LightRadius 
    {
    public:
        void SetRadius(float radius) { m_radius = radius; }
        float GetRadius() { return m_radius; }
    protected:
        glm::mat4 & PacketImpl(glm::mat4 & data) {
            data[2].x = m_radius;
            return data;
        }
    protected:
        float m_radius{1.0f};
    
    };
    
    template<int type, typename... Comp>
    class LightMixin : public Comp...
    {
        REF_ENABLE
    public:
        glm::mat4 Packet() {
            glm::mat4 data(0.0f);
            data[0].w = (float)type;
            (Comp::PacketImpl(data), ...);
            return data;
        }
    };
    
    using PointLight = LightMixin<0, LightCommon, LightPosition>;
    REF_REGISTER_CLASS(PointLight,
        REF_REGISTER_FIELD(PointLight, m_color),
        REF_REGISTER_FIELD(PointLight, m_energy),
        REF_REGISTER_FIELD(PointLight, m_pos)
    )
    
    using DirectLight = LightMixin<1, LightCommon, LightDirect>;
    REF_REGISTER_CLASS(DirectLight,
        REF_REGISTER_FIELD(DirectLight, m_color),
        REF_REGISTER_FIELD(DirectLight, m_energy),
        REF_REGISTER_FIELD(DirectLight, m_dir)
    )
    
    using AmbientSphereLight = LightMixin<2, LightCommon, LightPosition, LightRadius>;
    REF_REGISTER_CLASS(AmbientSphereLight,
        REF_REGISTER_FIELD(AmbientSphereLight, m_color),
        REF_REGISTER_FIELD(AmbientSphereLight, m_energy),
        REF_REGISTER_FIELD(AmbientSphereLight, m_pos),
        REF_REGISTER_FIELD(AmbientSphereLight, m_radius)
    )
} // namespace SEngine


#endif